<?php
namespace app\common\repositories\user;
use app\common\model\user\User;
use app\common\repositories\BaseRepository;
use app\common\dao\user\UserDao as dao;
use app\common\repositories\member\MemberRecordRepository;
use basic\exceptions\AuthException;
use basic\services\JwtTokenService;
use basic\services\WechatService;
use think\exception\ValidateException;
use think\facade\Cache;
use think\facade\Config;
use think\facade\Db;

/**
 * @mixin dao
 */
class UserRepository extends BaseRepository
{
    protected string $apiField = 'uid,nickname,real_name,avatar,company_name,identity_id,business_id,sex,city_id,work_limit,tag,self_tag,view,integral'; //performance,desc,

    public function __construct(dao $dao)
    {
        $this->dao = $dao;
    }


    public function openMember($uid,$member)
    {

        $data = [
            'order_sn'=>getOrderSn('M'),
            'status'=>0,
            'uid'=>request()->uid(),
            'to_uid'=>$uid,
            'member_id'=>$member->member_id,
            'member_title'=>$member->title,
            'count'=>$member->count,
            'type'=>$member->type,
            'price'=>$member->price,
        ];

        app()->make(MemberRecordRepository::class)->create($data);

        // # todo 微信支付
       // $this->openMemberSuccess($data['order_sn']);
        return WechatService::create()->jsPay(request()->userInfo()->wechat_openid,$data['order_sn'],bcmul(100,$data['price']),'开通会员套餐','member');

    }


    public function openMemberSuccess($orderSn)
    {
       $record =  app()->make(MemberRecordRepository::class)->getWhere(['order_sn'=>$orderSn,'status'=>0]);
       if(!$record) {
           return;
       }
       $user = $this->dao->get($record->to_uid);
       if($record->type == 1){
            // 线索
            $this->incrNumberField($user->uid,'integral',$record->count);
       }else{
           //
           $user->save(['course_member'=>1]);
       }

        $record->save(['status'=>1]);
    }




    public function getList($where,$page,$limit)
    {
        $query = $this->dao->search($where);
        $count = $query->count();
        $list = $query->page($page,$limit)->order('uid DESC')->select();
        return compact('list','count');
    }


    public function getApiList($where,$page,$limit)
    {
        $where['is_sign'] = 1;
        $where['status'] = 1;
        $query = $this->dao->search($where);
        $count = $query->count();
        $query->with(['leader']);
        $list = $query->page($page,$limit)->field($this->apiField)->select();
        $list->append(['identity','business','city','member_name','role']);
        return compact('list','count');
    }


    public function getLatelyList($count = 10)
    {
        $count = $count > 20 ? 20 : $count;
        $key = 'lately_sign_user_list_1'.$count;
        if(Cache::has($key)) {
            $list = Cache::get($key);
        }else{
            $where['is_sign'] = 1;
            $query = $this->dao->search($where);
            $list = $query->order('sign_time DESC')->field($this->apiField)->limit($count)->select();
            $list->append(['identity','business','city','member_name']);
            Cache::set($key,$list->toArray(),3600);
        }
        return compact('list');
    }


    /**
     * 用户基础信息
     * @param $id
     * @return \app\common\model\BaseModel|array|\think\Model|null
     * User: xiest
     * Date: 2021/12/3
     */
    public function basicDetail($id)
    {
        $userInfo = $this->dao->getWhere(['uid'=>$id],$this->apiField,['leader']);
        if(!$userInfo) throw new ValidateException('用户不存在');
        $viewUid = (request()->isLogin() ? request()->uid() : null);
        $userInfo->append(['identity','business','city','member_name'])->toArray();

        //关注状态
        $userInfo['focus_status'] = app()->make(UserOperationRepository::class)
            ->getStatus('focus_user',$viewUid,$id);
        return $userInfo;
    }

    public function detail($id)
    {
        $viewUid = (request()->isLogin() ? request()->uid() : null);
        $self = $id == $viewUid;
        $field = $self ? ($this->apiField.',performance,desc,phone,balance,currency') : ($this->apiField.',performance,desc');
        
        $userInfo = $this->dao->getWhere(['uid'=>$id],$field,['leader']);
        if(!$userInfo) throw new ValidateException('用户不存在');

      /*  if(!$userInfo['is_sign'] && !$self)
            throw new ValidateException('用户未注册联盟');*/
        $userInfo->append(['identity','business','city','member_name'])->toArray();

        //关注状态
        $userInfo['focus_status'] = app()->make(UserOperationRepository::class)
            ->getStatus('focus_user',$viewUid,$id);

        if(!$self){
            $this->dao->incrNumberField($id,'view');
            checkMemberAuth($viewUid,'watch_project',$id,'watch_resource');
        }

        return $userInfo;
    }


    public function getViewDetail($viewUid,$id)
    {
        $userInfo = $this->dao->getWhere(['uid'=>$id],$this->apiField.',ext_url',['leader']);
        if(!$userInfo) return null;
        $userInfo->append(['identity','business','city','member_name','role'])->toArray();
        $userInfo['focus_status'] = app()->make(UserOperationRepository::class)
            ->getStatus('focus_user',$viewUid,$id);
        return $userInfo;
    }



    public function sign($id,$data)
    {
        Db::transaction(function ()use($id,$data){
            $this->dao->update($id,$data);
        });
    }

    public function setSpreadUser($uid,$fromCode)
    {
        $user = $this->dao->get($uid);
        if(!$user || $user->spread_uid) return;
        $fromUser = $this->dao->userInfoByShareCode($fromCode);
        if(!$fromUser || $fromUser->uid == $uid) return;

        $user->spread_uid = $fromUser->uid;
        $user->spread_time = date('Y-m-d H:i:s');
        $user->save();

        $freeCount = systemConfig('share_user_free_count') ? : 0;
        $this->dao->incrNumberField($user->spread_uid,'free_count',$freeCount);
    }


    public function syncWechatPhoneUser($openId)
    {
        $user = $this->dao->userInfoByOpenId($openId);

        if($user){
            $user->save(['openid'=>$openId]);
        }else{
            $user = $this->dao->create([
                'share_code'=>'',//$this->createInviteCode(),
                'nickname'=> '用户'.mt_rand(1000,299999),
                'phone'=>'',
                'openid'=>$openId
            ]);
        }

        return $this->dao->get($user->uid);
    }



    /**
     * 小程序同步用户信息
     * @param $openid
     * @param $userInfo
     * @return \app\common\model\BaseModel|array|\think\db\BaseQuery|\think\Model|null
     * User: xiest
     * Date: 2021/10/5
     */
    public function syncUser($openid,$userInfo)
    {
        $routineInfo['nickname'] = filter_emoji($userInfo['nickName']??"");//姓名
        $routineInfo['sex'] = $userInfo['gender']??"";//性别
        $routineInfo['city'] = $userInfo['city']??"";//城市
        $routineInfo['province'] = $userInfo['province']??"";//省份
        $routineInfo['avatar'] = $userInfo['avatarUrl']??"";//头像
        $routineInfo['openid'] = $openid;//openid
        $routineInfo['unionid'] = $userInfo['unionid']??"";
        $routineInfo['phone'] = $userInfo['phone'];
        $user = $this->dao->userInfoByOpenId($openid);
        if(!$user && $routineInfo['unionid']) {
            $user = $this->dao->userInfoByUnionId($userInfo['unionid']);
        }
        if(!$user) {
            Db::transaction(function () use ($routineInfo){
                $user = $this->dao->create($routineInfo);
            });
        }else{
            $user->save($routineInfo);
        }
        return $this->dao->get($user->uid);
    }


    public function createInviteCode(): string
    {
        $code = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
        $rand = $code[rand(0,25)]
            .strtoupper(dechex(date('m')))
            .date('d')
            .substr(time(),-5)
            .substr(microtime(),2,5)
            .sprintf('%02d',rand(0,99));
        for(
            $a = md5( $rand, true ),
            $s = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ',
            $d = '',
            $f = 0;
            $f < 6;
            $g = ord( $a[ $f ] ),
            $d .= $s[ ( $g ^ ord( $a[ $f + 8 ] ) ) - $g & 0x1F ],
            $f++
        );
//        if($this->dao->userInfoByShareCode($d)){
//            return $this->createInviteCode();
//        }
        return $d;
    }


    /**
     * 同步微信登录信息
     * @param $openid
     * @param $userInfo
     * User: xiest
     * Date: 2022/2/16
     */
    public function syncWechatUser($userInfo)
    {
        $info['nickname'] = filter_emoji($userInfo['nickname']??'');//姓名
        $info['sex'] = $userInfo['sex']??"";//性别   1男  2女  0未知
        $info['city'] = $userInfo['city']??"";//城市
        $info['province'] = $userInfo['province']??"";//省份
        $info['avatar'] = $userInfo['headimgurl']??"";//头像

        $info['wechat_openid'] = $userInfo['openid'] ??'';//openid
        $info['unionid'] = $userInfo['unionid']??"";

        $user = $this->dao->userInfoByPhone($userInfo['phone']);
//        if(!$user && $info['unionid']) {
//            $user = $this->dao->userInfoByUnionId($info['unionid']);
//        }

        if(!$user) {
            if(!$info['nickname']){
                $info['nickname'] = '用户'.$this->createInviteCode();
            }
            //$info['real_name'] = $info['nickname'];
            $user = $this->dao->create($info);
        }else{
            $newData['phone'] = $userInfo['phone'];
            if($info['nickname']){
                $newData['nickname'] = $info['nickname'];
            }
            if($info['avatar']){
                $newData['avatar'] = $info['avatar'];
            }
            if($info['wechat_openid']){
                $newData['wechat_openid'] = $info['wechat_openid'];
            }
            $user->save($newData);
        }
        return $this->dao->get($user->uid);
    }




    public function loginAfter(User $user)
    {
        $user->last_login_ip = request()->ip();
        $user->last_login_time = date('Y-m-d H:i:s');
        $user->save();
    }


    public function createToken(User $user)
    {
        $service = new JwtTokenService();
        $token = $service->createToken($user->uid,'user',time()+Config::get('admin.user_token_valid_exp',3600*24*30));
        $this->cacheToken($token['token'],Config::get('admin.user_token_valid_exp',3600*24*30));
        return $token;
    }


    public function cacheToken(string $token,int $exp)
    {
        Cache::store('file')->set('user_' . $token, time(), $exp);
    }


    public function updateToken(string $token)
    {
        Cache::store('file')->set('user_'.$token,time(),Config::get('admin.user_token_valid_exp',3600*24*30));
    }


    public function checkToken(string $token)
    {
        $cache = Cache::store('file');
//        if(!$cache->has('user_'.$token))
//            throw new AuthException('登录状态已失效');
//        $lastTime = $cache->get('user_'.$token);
//        if(($lastTime + (Config::get('admin.user_token_valid_exp',3600*24*30))) < time())
//            throw new AuthException('token 已过期');
    }

    public function clearToken(string $token)
    {
        Cache::store('file')->delete('user_'.$token);
    }


}